package es.ibm.santillana.mdm.mqseries;

import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.Properties;
import java.util.Queue;
import java.util.Scanner;

import com.ibm.mq.MQC;
import com.ibm.mq.MQEnvironment;
import com.ibm.mq.MQException;
import com.ibm.mq.MQMessage;
import com.ibm.mq.MQPutMessageOptions;
import com.ibm.mq.MQQueue;
import com.ibm.mq.MQQueueManager;
import com.ibm.mq.constants.CMQC;

import es.ibm.santillana.mdm.common.util.ConstSantillana;

public class SantillanaMQ {

	private MQQueueManager _queueManager = null;
	public int port;// = 1414;//1422
	public String hostname;// = "10.125.141.51";
	public String channel;// = "TEST_SVRCONN";
	public String qManager;// = "gcMDM";
	public String outputQName;// = "inputMDM";
	public String user; //"Usuario"
	public Queue<String> messageQueue = new LinkedList<String>();
	public Queue<String> messageNamesQueue = new LinkedList<String>();
	
	public SantillanaMQ() throws IOException {
		super();
		Properties prop = new Properties();
		//TODO: Pruebas Locales.
		String propertiesName = "params.properties";
		String propertiesPath = ConstSantillana.PROPERTIES_PATH + propertiesName;
		InputStream input = new FileInputStream(propertiesPath);
		prop.load(input);
		System.out.println("SantillanaMQ properties");
		
		port = new Integer (prop.getProperty("port","1414"));
		hostname = prop.getProperty("hostname");
		channel = prop.getProperty("channel");
		qManager = prop.getProperty("qManager");
		outputQName = prop.getProperty("outputQName");
		user = prop.getProperty("user");
		
		messageQueue = getPendingMessages();
		System.out.println("Mensaje pendientes en cola ->" + messageQueue.size());
		
//		
//		hostname = "10.125.143.53";
//		channel = "TEST_SVRCONN2";
//		qManager = "gcSantillana";
//		outputQName = "MQ_0018_MDM";
//		user = "BenitoPerez";
//		
//		hostname = "10.127.1.43";
//		channel = "MDM_CONN";
//		qManager = "qmSesPre";
//		outputQName = "MQ_0018_MDM";
//		user = "mdmUser";
				
		System.out.println("Encolando");		
		System.out.println("Port: " + port + "hostname: " + hostname + " channel: " + channel + "qManager: " + qManager + "outputQNAme: " + outputQName );		
	
		//input.close();
	}

	public void init() {
		// Set up MQ environment
		MQEnvironment.hostname = hostname;
		MQEnvironment.channel = channel;
		MQEnvironment.port = port;
		MQEnvironment.userID = user;
		MQEnvironment.properties.put(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES);
		//MQEnvironment.CCSID = 1208;
	}

	public void enviaXML() {
	
		MQQueueManager qMgr = null;
		MQQueue sendingQueue = null;
		
		MQEnvironment.hostname = hostname;
		MQEnvironment.channel = channel;
		MQEnvironment.userID = user;
		MQEnvironment.port = port;
		MQEnvironment.properties.put(MQC.TRANSPORT_PROPERTY,MQC.TRANSPORT_MQSERIES_CLIENT);
		
		try {
			
			qMgr = new MQQueueManager(qManager); 
			int openOutOptions = CMQC.MQOO_OUTPUT;
			sendingQueue = qMgr.accessQueue(outputQName.trim(),openOutOptions,null,null,null);
			
			System.out.println("Mensajes que se van a enviar ->" + messageQueue.size());
			Integer numMessages = messageQueue.size();
			
			for (int i = 0; i < numMessages ; i++) {
				
				System.out.println("Envio mensaje -> " + i);
				System.out.println(messageQueue.peek());
				
				MQMessage sendingMessage = new MQMessage();
				sendingMessage.persistence = CMQC.MQPER_PERSISTENCE_AS_Q_DEF;

				try {
					sendingMessage.writeString(messageQueue.peek());
				} catch (IOException e) {
					// TODO Auto-generated catch block
					System.out.println("Error al escribir el mensaje");
					e.printStackTrace();
				}
				
				// Specify the message options..
				MQPutMessageOptions pmo = new MQPutMessageOptions();
				// Put message on the queue
				sendingQueue.put(sendingMessage,pmo);  
				
				System.out.println("Saco el mensaje de la cola");
				messageQueue.poll();
				messageNamesQueue.poll();
				System.out.println("Mensajes que quedan en la cola -> " + messageQueue.size());
				
				File folderPending = new File(ConstSantillana.PATH_PENDING);
				File[] listFiles = folderPending.listFiles();
				if (listFiles.length > 0) {
					Arrays.sort(listFiles, new Comparator<File>(){
						public int compare(File o1, File o2) {
							int index1 = Integer.parseInt(o1.getName().split("-")[0].trim());
							int index2 = Integer.parseInt(o2.getName().split("-")[0].trim());
							return index1 - index2;
						}
					});
					listFiles[0].delete();
					System.out.println("Mensaje pendiente borrado y enviado");
					System.out.println("Mensajes que quedan pendientes de enviar -> " + listFiles.length);
				}
				
				System.out.println("Mandado y el que ha mandado ha descansado");
			}
			
		} catch (IllegalArgumentException e) {
			System.out.println("Usage: java MQRead <-h host> <-p port> <-c channel> <-m QueueManagerName> <-q QueueName>");
			createFilePendingInServer();
			e.printStackTrace();
		} catch (MQException e) {
			System.out.println(e);
			createFilePendingInServer();
			e.printStackTrace();
		} finally {
			try {
				if (sendingQueue != null) sendingQueue.close();
				if (qMgr != null) qMgr.disconnect();
			} catch (MQException e) {
				e.printStackTrace();
			}
			
		}
		
	}

	private void createFilePendingInServer() {
		
		File folderPending = new File(ConstSantillana.PATH_PENDING);
		File[] listFiles = folderPending.listFiles();
		
		for (File file : listFiles) {
			file.delete();
		}
		
		for (String xml : messageQueue) {
			createFilePending(xml);
		}
	}

	private void createFilePending(String XML) {
		
		try {
			String pathPending = ConstSantillana.PATH_PENDING;
			
			File folderPending = new File(ConstSantillana.PATH_PENDING);
			File[] listFiles = folderPending.listFiles();
			
			Integer index = 1;
			if (listFiles.length > 0) {
				Arrays.sort(listFiles, new Comparator<File>(){
					public int compare(File o1, File o2) {
						int index1 = Integer.parseInt(o1.getName().split("-")[0].trim());
						int index2 = Integer.parseInt(o2.getName().split("-")[0].trim());
						return index1 - index2;
					}
				});
				index = listFiles.length + 1;
			}
			
			String ruta = pathPending.concat(index.toString()).concat("-").concat(messageNamesQueue.poll());
			File archivo = new File(ruta);

			if (!archivo.exists()) {
				BufferedWriter bw;
				bw = new BufferedWriter(new FileWriter(archivo));
				bw.write(XML);
				bw.close();
			}
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	public LinkedList<String> getPendingMessages() {
		File pathPending = new File(ConstSantillana.PATH_PENDING);
		File[] listFiles = pathPending.listFiles();
		
		Arrays.sort(listFiles, new Comparator<File>(){
			public int compare(File o1, File o2) {
				int index1 = Integer.parseInt(o1.getName().split("-")[0].trim());
				int index2 = Integer.parseInt(o2.getName().split("-")[0].trim());
				return index1 - index2;
			}
		});
		
		LinkedList<String> listMessages = new LinkedList<String>();
		for (File message : listFiles) {
			try {
				Scanner sc = new Scanner(message);
				String xmlMessage = "";
				
				while (sc.hasNextLine()) {
					xmlMessage += sc.nextLine();
				}
				
				listMessages.add(xmlMessage);
				sc.close();
				messageNamesQueue.add(message.getName().split("-")[1]);
				
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}
		}
		System.out.println("Mensajes pendientes en servidor -> "  + listMessages.size());
		return listMessages;
	}
	
	public static void main(String[] args) {

		SantillanaMQ readQ;
		try {
			readQ = new SantillanaMQ();
			readQ.init();
			readQ.selectQMgr();
			//readQ.read();
			readQ.write("Prueba a lo loco");
		} catch (IllegalArgumentException e) {
			System.out.println("Usage: java MQRead <-h host> <-p port> <-c channel> <-m QueueManagerName> <-q QueueName>");
			e.printStackTrace();
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (MQException e) {
			System.out.println(e);
			e.printStackTrace();
		}
	}

//	private void read() throws MQException {
//		int openOptions = MQC.MQOO_INQUIRE + MQC.MQOO_FAIL_IF_QUIESCING
//				+ MQC.MQOO_INPUT_SHARED;
//
//		MQQueue queue = _queueManager.accessQueue(inputQName, openOptions,
//				null, // default q manager
//				null, // no dynamic q name
//				null); // no alternate user id
//
//		System.out.println("MQRead v1.0 connected.\n");
//
//		int depth = queue.getCurrentDepth();
//		System.out.println("Current depth: " + depth + "\n");
//		if (depth == 0) {
//			return;
//		}
//
//		MQGetMessageOptions getOptions = new MQGetMessageOptions();
//		getOptions.options = MQC.MQGMO_NO_WAIT + MQC.MQGMO_FAIL_IF_QUIESCING
//				+ MQC.MQGMO_CONVERT;
//		while (true) {
//			MQMessage message = new MQMessage();
//			try {
//				queue.get(message, getOptions);
//				byte[] b = new byte[message.getMessageLength()];
//				message.readFully(b);
//				System.out.println(new String(b));
//				message.clearMessage();
//			} catch (IOException e) {
//				System.out.println("IOException during GET: " + e.getMessage());
//				break;
//			} catch (MQException e) {
//				if (e.completionCode == 2
//						&& e.reasonCode == MQException.MQRC_NO_MSG_AVAILABLE) {
//					if (depth > 0) {
//						System.out.println("All messages read.");
//					}
//				} else {
//					System.out.println("GET Exception: " + e);
//				}
//				break;
//			}
//		}
//		queue.close();
//		_queueManager.disconnect();
//	}

	private void selectQMgr() throws MQException {
		_queueManager = new MQQueueManager(qManager);
	}

	private void write(String xml) throws MQException {
		int lineNum = 0;
		int openOptions = MQC.MQOO_OUTPUT + MQC.MQOO_FAIL_IF_QUIESCING;
		try {
			MQQueue queue = _queueManager.accessQueue(outputQName, openOptions,
					null, // default q manager
					null, // no dynamic q name
					null); // no alternate user id

			DataInputStream input = new DataInputStream(System.in);

			System.out.println("MQWrite v1.0 connected");
			System.out.println("and ready for input, terminate with ^Z\n\n");

			// Define a simple MQ message, and write some text in UTF format..
			MQMessage sendmsg = new MQMessage();
			sendmsg.format = MQC.MQFMT_STRING;
			sendmsg.feedback = MQC.MQFB_NONE;
			sendmsg.messageType = MQC.MQMT_DATAGRAM;
			sendmsg.replyToQueueName = "ROGER.QUEUE";
			sendmsg.replyToQueueManagerName = qManager;

			MQPutMessageOptions pmo = new MQPutMessageOptions(); // accept the
																	// defaults,
																	// same
			// as MQPMO_DEFAULT constant

			String line = xml;
			sendmsg.clearMessage();
			sendmsg.messageId = MQC.MQMI_NONE;
			sendmsg.correlationId = MQC.MQCI_NONE;
			sendmsg.writeString(line);

			// put the message on the queue
			//TODO: Aqui se quita la cola
			queue.put(sendmsg, pmo);
			System.out.println(++lineNum + ": " + line);

			queue.close();
			_queueManager.disconnect();

		} catch (com.ibm.mq.MQException mqex) {
			System.out.println(mqex);
		} catch (java.io.IOException ioex) {
			System.out.println("An MQ IO error occurred : " + ioex);
		}

	}
}